<?php 

/**
 *childInfo options:
 * allowEdit : to allow edit of already added children
 * deleteMissing : delete children that were not present in the edit data.
 * Enter description here ...
 * @author ADMIN
 *
 */
class ParentFieldType extends GigaFieldType
{
	var $addFieldLink = '<div align="right">
		<a class="addAnotherField" id=":linkId" href="javascript:void(0);" rel=":templateVar">:addAnotherLabel</a>
		</div>';
	function _getFieldHtml($form, $childInfo, $field, $counter)
	{
		//prd($form->params['data']);
		$isPost = false;
		$validationErrors = false;
		if(!empty($form->validationErrors))
		{
			$validationErrors = $form->validationErrors;
		}
		if(!empty($form->params['data']))
		{
			$isPost = true;
		}
		
		$parentModel = $form->model();
		if(strpos($field,$parentModel.'.') === 0)
		{
			$field = substr($field,strlen($parentModel.'.'));
		}
		extract($childInfo);
		
		$childModel = Utility::getModelObject($model);
		$fields = $childModel->getFields('group', $child_group);
		$fieldHtml = '<div class="fieldWrap">';
		
		$count = count($fields);
		$class = 'horizontalInput-'.$count." input text";
		//using full url as Html::css appends /app/webroot in case of base url is present.
		$form->Html->css($form->Html->url('/cms/horizontalInput/'.$count.'/count.css',true),null,array(),false);
		
		if($this->editing && (!isset($childInfo['allowEdit']) || $childInfo['allowEdit'] == true))
		{
			$fields = am(array('id'), $fields);
			//echo "editing"; exit;
		}
		
		foreach($fields as $fieldName)
		{
			$properties = $childModel->getFieldProperties($fieldName);
			if((isset($childInfo['allowEdit']) && $childInfo['allowEdit'] == false))
			{
				$properties['value'] = "";
			}
			if(isset($properties['div']))
			{
				$properties['div'] .= " ". $class;
			}
			else
			{
				$properties['div'] = $class;
			}
			// check validation errors
			if($isPost && $validationErrors)
			{
				$msg = false;
				if(isset($validationErrors[$parentModel][$childModel->alias][$counter][$fieldName]))
				{
					$msg = $validationErrors[$parentModel][$childModel->alias][$counter][$fieldName];
				}else if(isset($validationErrors[$childModel->alias][$counter][$fieldName]))
				{
					$msg = $validationErrors[$childModel->alias][$counter][$fieldName];
				}
				if($msg)
				{
					$properties['after'] = '<div class="error-message">'.$msg.'</div>';
				}
			}
			if($fieldName == 'id')
			{
				$properties['type'] = 'hidden';
			}
			$fieldHtml .= $form->input($parentModel.'.'.$field.'.'.$counter.'.'.$fieldName, $properties);
			
		}
		$onclick = "$(this).parent().parent().remove();";
		$fieldHtml  .=  '<span style="display: block; padding-top:20px;" class="delete_child">';
		$fieldHtml .= $form->Html->link("",'javascript:void(0)',array('onclick'=>$onclick,'escape'=>false,'style'=>"padding-top:20px",'class'=>"crossIcon",'title'=>__("Delete")));
		$fieldHtml .='</span>';
		$fieldHtml .= '</div>';
		return $fieldHtml;
	}
	
	function getFormOptions($form, $field, $options)
	{
		$this->editing = false;
		
		$parentModel = $form->model();
		$parentModelObject = Utility::getModelObject($parentModel);
		$childInfo = $options['childInfo'];
		// alter $form->data while editing to populate parent field well
		// case 1: 'data' was auto-fetched via model assoc
		if(strpos($childInfo['model'], '.'))
		{
			$childInfo['model'] = end(explode('.', $childInfo['model']));
		}
		if(isset($form->data[$childInfo['model']]))
		{
			$this->editing = true;
			$form->data[$parentModel][$field] = $form->data[$childInfo['model']];
			$fieldCount = count($form->data[$childInfo['model']]);
		}
		if(isset($form->data[$parentModel][$field]))
		{
			$this->editing = true;
			$fieldCount = count($form->data[$parentModel][$field]);
		}
		
		// case 2: data is not fetched, fetch it from here itself in that case
		if(!isset($fieldCount))
		{
			if(!empty($form->params['data']) && isset($form->params['data'][$parentModel][$field]) && (!isset($childInfo['allowEdit']) || $childInfo['allowEdit'] == true))
			{
				$fieldCount = count($form->params['data'][$parentModel][$field]);
			}
			else
			{
				$fieldCount = 1;
				if(isset($defaultCount))
				{
					$fieldCount = $defaultCount;
				}
				else
				{
					$fieldCount = 1;
				}
			}
		}
		$output = '';
		//hidden field in case no field is added.
		$output .= $form->input($parentModel.'.'.$field,array('type'=>"hidden","value"=>""));
		for($i = 0; $i < $fieldCount; $i++)
		{
			$output .= $this->_getFieldHtml($form, $childInfo, $field, $i);
		}

		$fieldHtml = $this->_getFieldHtml($form, $childInfo, $field, '{n}');
		if(isset($childInfo['allowMultiple']) && $childInfo['allowMultiple'] == true)
		{
			$templateVarName = $parentModel."_".$field."_childTemplate_".mt_rand(1, 100);
			$templateVarName = str_replace(".","_",$templateVarName);
			$js = "<script>window.".$templateVarName." = '".str_replace("\n", "", $fieldHtml)."';</script>";
			$linkId = $field.'_parent_field_add_more';
			if(isset($options['addMoreLabel']))
			{
				$addLinkLabel = $options['addMoreLabel'];
			}else
			{
				$fieldName = Inflector::humanize(Inflector::underscore($field));
				$fieldName = low(Inflector::pluralize($fieldName));
				$addLinkLabel = sprintf(__("Add more %s"),__($fieldName));
			}
			$output .= $js. String::insert($this->addFieldLink, array('templateVar' => $templateVarName,'linkId'=>$linkId,'addAnotherLabel'=>$addLinkLabel));
		}
		if(!isset($options['fieldset']) || $options['fieldset'] == true)
		{
			$output = '<fieldset><legend>'.__($options['label']).'</legend>'.$output.'</fieldset>';
		}else
		{
			$output = '<div><label>'.$options['label'].'</label>'.$output.'</div>';
		}
		
		$options = array('output' => $output);
		return $options;
	}
	
	function beforeSaveAll(AppModel $model)
	{
		$fields = $model->getFields('type', 'parent');
		$parentId = null;
		$isNew = false;
		if(!isset($model->saveAllData[$model->alias][$model->primaryKey]))
		{
			$isNew = true;
		}
		if($isNew == false)
		{
			$parentId = $model->saveAllData[$model->alias][$model->primaryKey];
		}
		foreach($fields as $field)
		{	
			if(isset($model->saveAllData[$model->alias][$field]) && $model->getFieldProperty($field,'ignoreCallback') == false)
			{
				$childInfo = $model->getFieldProperty($field, 'childInfo');
				$childModel = cri($childInfo['model']);
				
				
				$parentFieldData = $model->saveAllData[$model->alias][$field];
				if(!$parentFieldData)
				{
					$parentFieldData = array();
				}
				if(method_exists($childModel, 'beforeChildrenSave'))
				{
					//send instance of ParentModel Also.
					$parentFieldData = $childModel->beforeChildrenSave($parentFieldData,$model);
				}
				if($parentFieldData)
				{
					$childModel->saveAllData[$childModel->alias] = $parentFieldData;
				}else
				{
					$childModel->saveAllData = array();
				}
				//pr($childModel->saveAllData);
				// because parent can have other special field types too
				GigaFieldTypesHandler::trigger($childModel->getDistinctFieldTypes(), 'beforeSaveAll', array($childModel));
				//prd($childModel->saveAllData);	
				if($isNew == false && (!isset($childInfo['deleteMissing']) || $childInfo['deleteMissing'] == true))
				{
					$this->deleteMissingChildren($childModel,$model,$parentId);
				}
				foreach($childModel->saveAllData as $modelAlias => $record)
				{
					$model->saveAllData[$modelAlias] = $record;
				}
				unset($model->saveAllData[$model->alias][$field]);

			}
		}
	}
	/**
	 * Delete childrens that were deleted during editing,
	 * @param AppModel $childModel
	 * @param AppModel $parentModel
	 * @param unknown_type $parentId
	 */
	private function deleteMissingChildren(AppModel $childModel,AppModel $parentModel,$parentId)
	{
    $parentKey = $parentModel->foreignKey;
		$oldChildrenIds = $childModel->find('list',array('conditions'=>array($parentKey => $parentId),'fields'=>array($childModel->primaryKey)));
		$presentChidlrenIds = @Set::extract($childModel->saveAllData[$childModel->alias],'{n}.'.$childModel->primaryKey);
		if(!is_array($presentChidlrenIds))
		{
			$presentChidlrenIds = array();
		}
		$deletedChildrenIds = array_diff($oldChildrenIds,$presentChidlrenIds);
		foreach($deletedChildrenIds as $deletedChild)
		{
			$childModel->delete($deletedChild);
		}
	}
	/* This was the older code, which made parent fields work with save() calls as well, but
	 * due to the time factor, currently we will not support save() rather there will be a 
	 * restriction to use saveAll() when using 'parent' field type. Do not delete the code below.
	function beforeSave($model)
	{
		$fields = $model->getFields('type', 'parent');
		$db = ConnectionManager::getDataSource($model->useDbConfig);
		
		//pr($model->data);
		foreach($fields as $field)
		{
			if(isset($model->data[$model->alias][$field]))
			{
				$startTransaction = true;
				break;
			}
		}
		
		if($db->_transactionStarted)
			$startTransaction = false;
		
		if(!$startTransaction)
		{
			return;
		}
		
		$db->begin($model);
	}
	
	function afterSave($model, $created)
	{
		$db = ConnectionManager::getDataSource($model->useDbConfig);
		$fields = $model->getFields('type', 'parent');
		foreach($fields as $field)
		{
			if(isset($model->data[$model->alias][$field]))
			{
				$childInfo = $model->getFieldProperty($field, 'childInfo');
				$return = cri($childInfo['model'])->saveChildren($model->data[$model->alias][$field], $model->id);
				if(!$return)
				{
					$db->rollback($model);
					return false;
				}
			}
		}
		if($db->commit($model))
		{
			//$model->validationErrors[] = 'Commit failed';
			return true;
		}
		return false;
	}
	*/
}

?>